<template>
  <div class="app-container">
    <el-dialog
      v-dialogDrag
      :title="dialogTitle"
      style="padding: 0px;"
      :visible="dialogVisible"
      :before-close="cancelEidt"
      class="dialogStyleMiddle"
      :close-on-click-modal="false"
    >
      <el-row>
        <el-form v-if="dialogVisible" label-width="80px">
          <el-form-item label="菜单权限" class="el-tree-wrap">
            <p class="all-expand">
              <span v-if="AddExpand" @click="unFoldAll()"><i class="el-icon-caret-bottom" />全部展开</span>
              <span v-else @click="closeAll()"><i class="el-icon-caret-top" />全部关闭</span>
            </p>
            <!-- 菜单权限： -->
            <div>
              <el-tree
                v-if="openOrNot"
                ref="menu"
                :data="menuOptions"
                show-checkbox
                node-key="menuId"
                empty-text="加载中，请稍后"
                :props="defaultPropsMenu"
                :default-expand-all="defaultExpand"
                :highlight-current="true"
                :render-content="renderContent"
                @check="handleChange"
              />
            </div>
          </el-form-item>
        </el-form>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button size="medium" @click="cancelEidt">取 消</el-button>
        <el-button size="medium" type="primary" :disabled="btnDisabled" @click="submitFrom()">保 存</el-button>
      </span>
    </el-dialog>
    <!-- 引入时间改变弹框 -->
    <menus-time v-if="menusTimeVisible" ref="menuTime" @menuData="getMenuData" />
  </div>
</template>
<script>
import { Message } from 'element-ui'
import MenusTime from './MenusTime'
import { list, assignedMenu, selectMenuDetail, addOrupdateEnterpriseMenu } from '@/api/enterprise/changeMenus'
export default {
  components: {
    'menus-time': MenusTime
  },
  data() {
    return {
      AddExpand: true,
      openOrNot: true,
      defaultExpand: false,
      // 选中的菜单树数据
      treeSelected: [],
      // 树是否全部展开
      // 弹出的对话框的标题
      dialogTitle: '',
      // 对话框是否弹出显示
      dialogVisible: false,
      // 子组件是否弹框定义
      menusTimeVisible: false,
      /* * 树形菜单 */
      // 默认勾选节点key的值
      checkedKeys: [],
      // 树形菜单数据
      menuOptions: [],
      // 加载树形菜单结构
      defaultPropsMenu: {
        children: 'children',
        label: 'menuName'
      },
      // 企业id
      enterpriseId: '',
      // 分公司id
      subCompany: '',
      menuIds: [],
      // 用于封装 整个菜单树 数据权限的数组
      objIdAndMenuListAll: [],
      // 某个节点的数据
      singleMenu: '',
      btnDisabled: false
    }
  },
  methods: {
    // 全部展开
    unFoldAll() {
      this.treeSelected = this.$refs.menu.getCheckedKeys().concat(this.$refs.menu.getHalfCheckedKeys())
      this.AddExpand = false
      this.defaultExpand = true
      this.openOrNot = false
      setTimeout(() => {
        this.openOrNot = true
        this.$nextTick(() => {
          this.$refs.menu.setCheckedKeys(this.treeSelected)
        })
      }, 10)
    },
    // 全部关闭
    closeAll() {
      this.treeSelected = this.$refs.menu.getCheckedKeys().concat(this.$refs.menu.getHalfCheckedKeys())
      this.AddExpand = true
      this.defaultExpand = false
      this.openOrNot = false
      setTimeout(() => {
        this.openOrNot = true
        this.$nextTick(() => {
          this.$refs.menu.setCheckedKeys(this.treeSelected)
        })
      }, 10)
    },
    showView(enterpriseId, subCompany) {
      this.dialogTitle = '修改企业菜单和时间'
      this.dialogVisible = true
      this.enterpriseId = enterpriseId
      this.subCompany = subCompany
      // 获取树形菜单
      this.getMenuTreeData()
    },
    // 整个树形菜单加载
    getMenuTreeData() {
      list().then(resp => {
        if (resp) {
          this.menuOptions = resp.data
          this.selectedMenuIds(this.enterpriseId, this.subCompany)
        }
      })
    },
    // 菜单树形加载
    selectedMenuIds(enterpriseId, subCompany) {
      assignedMenu(enterpriseId, subCompany).then(resp => {
        if (resp) {
          const menuList = resp.data.sysMenus
          for (let j = 0; j < menuList.length; j++) {
            // 该企业选中的菜单节点，其中的到期时间和状态回显到菜单树中
            if (menuList[j].menuType === 'C') {
              this.menuOptions = this.tickMenuIdFilter(menuList[j].menuId, menuList[j].endTime, menuList[j].status).filter(this.menuOptions)
            }
          }
          this.$refs.menu.setCheckedKeys(resp.data.menuIds)
        }
      })
    },
    // 获取选中的所有菜单节点数据
    getMenuAllCheckedKeys() {
      // 目前被选中的菜单节点
      const checkedKeys = this.$refs.menu.getHalfCheckedKeys()
      // 半选中的菜单节点
      const halfCheckedKeys = this.$refs.menu.getCheckedKeys()
      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
      return checkedKeys
    },

    // 菜单树节点加载 设置菜单后面是否显示“数据权限”字样
    renderContent(h, { node, data, checked, store }) {
      // 判断菜单类型
      const menuType = data.menuType
      // 判断节点是否选中
      let isNodeCheck = false
      /** 当节点是选中状态时显示数据权限
       * 当节点是半选中状态时也显示数据权限
       */
      if (node.checked) {
        isNodeCheck = true
      } else {
        /** 获取次节点下面的子节点
         * 当子节点其中也有选择状态时设置isNodeCheck = true
         * 并且跳出循环
         */
        const childNodes = node.childNodes
        for (let i = 0; i < childNodes.length; i++) {
          if (childNodes[i].checked) {
            isNodeCheck = true
            break
          }
        }
      }
      /**
       * 当菜单类型为菜单（C）时 并且 次菜单是选中状态或者半选中状态
       * 否则并且不显示 “数据权限字样”
       */
      if (menuType === 'C' && isNodeCheck) {
        return (
          <span class='custom-tree-node'>
            <span>{data.menuName}</span>
            <span style='margin-left:20px'>
              <el-button
                size='mini'
                type='text'
                on-click={() => this.append(data, event)}
              >
                修改时间
              </el-button>
            </span>
          </span>
        )
      } else {
        return (
          <span class='custom-tree-node'>
            <span>{ data.menuName }</span>
          </span>
        )
      }
    },
    // 点击数据权限是调用的方法
    append(data, event) {
      this.menusTimeVisible = true
      this.$nextTick(() => {
        this.$refs.menuTime.showView(data, event)
      })
    },

    // 获取子集传过来的数据权限对象，并遍历菜单树放到对应节点的数据权限存放的字段（dataScopList）中
    getMenuData(menuData) {
      const menuId = menuData.menuId
      const endTime = menuData.endTime
      const status = menuData.status
      // 遍历菜单树，把数据权限存储到节点的dataScopList中
      const menuOptions = this.tickMenuIdFilter(menuId, endTime, status).filter(
        this.menuOptions
      )
      this.menuOptions = menuOptions
    },

    // 通过菜单id 查询菜单信息
    selectMenusByMenuId(menuId) {
      const enterpriseId = this.enterpriseId
      const subCompany = this.subCompany
      return selectMenuDetail(menuId, enterpriseId, subCompany)
    },
    // 循环改变菜单树形结构中的值
    changeMenuData(menuId, singleMenu) {
      // 节点的菜单的时间
      let endTime = ''
      let status = ''
      if (singleMenu != null && singleMenu !== '') {
        if (singleMenu.endTime !== null && singleMenu.endTime !== '') {
          endTime = singleMenu.endTime
        }
        if (singleMenu.status !== null && singleMenu.status !== '') {
          status = singleMenu.status
        }
      }
      const menuOptions = this.tickMenuIdFilter(
        menuId,
        endTime,
        status
      ).filter(this.menuOptions)
      this.menuOptions = menuOptions
    },

    async changeMenu(menuId) {
      try {
        const resp = await this.selectMenusByMenuId(menuId)
        if (resp) {
          const singleMenu = resp.data.data
          this.changeMenuData(menuId, singleMenu)
        }
      } catch (err) {
        // console.log(err)
      }
    },
    // 当复选框选中状态改变时
    handleChange(data, nodefunction) {
      // 定义变量用于判断当前节点有没有选择
      let isMenuId = true
      // 当天节点改变状态的值
      const menuId = data.menuId
      // 获取数组中被选中节点的值
      const checkedKeys = nodefunction.checkedKeys
      // 当前节点是选中状态标识设置为false
      for (let i = 0; i < checkedKeys.length; i++) {
        if (menuId === checkedKeys[i]) {
          isMenuId = false
        }
      }
      // isMenuId 为 true时 表示该节点没有被选中
      if (isMenuId && data.menuType === 'C') {
        // 当前节点没有被选中,遍历树 把该节点的到期时间和启用状态设置为最初值
        // 根据节点id查找该菜单节点
        this.changeMenu(menuId)
      } else if (isMenuId && data.menuType === 'M') {
        // 当目录节点没有被选中, 遍历树下面的菜单节点，菜单时间设置为最初值
        const dataMenuIds = this.getMenuIdFilter().filter(data)
        for (let j = 0; j < dataMenuIds.length; j++) {
          this.changeMenu(dataMenuIds[j])
        }
      }
    },

    /** 遍历整个菜单树结构 start
     *  menuId 菜单主键id
     *  defauleDataScopList 用于存储菜单数据权限的数组
     */
    tickMenuIdFilter: function(menuId, endTime, status) {
      let resultArr = []
      const getTickMenuId = function(obj) {
        if (undefined === obj || obj === null || !(obj instanceof Object)) {
          return
        }
        if (obj.menuId === menuId) {
          obj.status = status
          obj.endTime = endTime
        }
        if (obj.children != null && obj.children instanceof Array) {
          for (const child of obj.children) {
            getTickMenuId(child)
          }
        }
      }

      return {
        /**
         *  arr 树形菜单的数据
         */
        filter: function(arr) {
          resultArr = arr
          if (!(arr instanceof Array)) {
            return false
          }
          for (const rootMenu of arr) {
            getTickMenuId(rootMenu)
          }
          return resultArr
        }
      }
    },

    /**
     * 遍历菜单树中的一部分  获取菜单节点的菜单树id
     */
    getMenuIdFilter: function() {
      let resultArr = []
      const getTickMenuId = function(obj) {
        if (undefined === obj || obj === null || !(obj instanceof Object)) {
          return
        }
        if (obj.menuType === 'C') {
          resultArr.push(obj.menuId)
        }
        if (obj.children != null && obj.children instanceof Array) {
          for (const child of obj.children) {
            getTickMenuId(child)
          }
        }
      }

      return {
        filter: function(arr) {
          if (!(arr instanceof Array)) {
            return false
          }
          resultArr = []
          // for(let rootMenu of arr){
          //   getTickMenuId(rootMenu);
          // }
          getTickMenuId(arr)
          return resultArr
        }
      }
    },

    // 取消按钮（数据权限）
    cancelEidt() {
      this.dialogVisible = false
      this.btnDisabled = false
      this.objIdAndMenuListAll = []
    },

    // 创建用于存储ObjIdAndMenuList 的对象
    createObjIdAndMenuList(objId, menuList) {
      const objIdAndMenuList = {}
      objIdAndMenuList['enterpriseId'] = objId
      objIdAndMenuList['menuList'] = menuList
      return objIdAndMenuList
    },
    // 所有菜单节点数据
    getMenuAllCheckedNodes() {
      const checkedNodes = this.$refs.menu.getHalfCheckedNodes()
      const halfCheckedNodes = this.$refs.menu.getCheckedNodes()
      checkedNodes.unshift.apply(checkedNodes, halfCheckedNodes)
      return checkedNodes
    },
    // 确认按钮
    submitFrom() {
      this.objIdAndMenuListAll = []
      // 获取选中的节点
      const checkNode = this.getMenuAllCheckedNodes()
      // 把选中的节点存到menuList中
      const createObjIdAndMenuList = this.createObjIdAndMenuList(
        this.enterpriseId,
        checkNode
      )
      this.objIdAndMenuListAll.push(createObjIdAndMenuList)
      const objIdAndMenuListAll = this.objIdAndMenuListAll
      // 封装的数组转化成json串
      const jsonString = JSON.stringify(objIdAndMenuListAll)
      // 数据传输到后台
      this.btnDisabled = true
      addOrupdateEnterpriseMenu(jsonString).then(resp => {
        if (resp) {
          this.dialogVisible = false
          // 清空数组
          this.ObjIdAndMenuListAll = []
          this.msgSuccess('操作成功')
        } else {
          Message.error(resp.message)
        }
        this.btnDisabled = false
      })
    }
  }
}
</script>
